#ifndef __IOMANAGER_H__
#define __IOMANAGER_H__

#include"schedule.h"
#include<sys/epoll.h>
#include"timer.h"

namespace sylar{

class IOManager: public Scheduler, public TimerManager{
public:
    using ptr = std::shared_ptr<IOManager>;
    using RWMutexType = RWMutex;

    enum Event{
        NONE = 0x0, 
        READ = 0x1,    //  EPOLLIN
        WRITE = 0x4    // EPOLLOUT
    };
private:
    /// 定义一个事件类来描述,事件可能针对一个句柄
    struct FdContext{
        using MutexType = Mutex;
        /// 事件描述结构体
        struct EventContext{
            /// 需要知道事件在哪个调度器上执行
            Scheduler* scheduler = nullptr;           /// 事件执行的schedule
            std::shared_ptr<Fiber> fiber;  /// 事件的协程
            std::function<void()> cb;      /// 事件的回调
        };
        EventContext& getContext(Event event);
        void resetContext(EventContext& ctx);
        void triggerEvent(Event event);
        int fd = 0;                            /// 事件关联的句柄
        ///每种事件又分为读、写事件
        EventContext read;
        EventContext write;
        Event event = NONE;              /// 已注册的事件，表示在读还是在写
        MutexType mutex;
    };

public:
    IOManager(size_t threads=1, bool use_caller=true, const std::string& name="");
    ~IOManager();

    // 0成功， -1失败
    int addEvent(int fd, Event event, std::function<void()> cb=nullptr);

    bool delEvent(int fd, Event event);
    bool cancelEvent(int fd, Event event);
    // 取消所有事件
    bool cancelAll(int fd);

    void contextResize(size_t size);

    static IOManager* GetThis();

    bool stopping(uint64_t &timeout);

protected:

    void onTimerInsertedAtFront() override;

    void tickle() override;

    bool stopping() override;


    /**
     * @brief 协程无任务可调度时执行idle协程
     * 解决当协程调度器无任务，又不能让线程终止的情况
     */ 
    void idle() override;

public:
    int m_epfd = 0;   //epoll句柄
    int m_tickleFds[2];                         //用于唤醒epfd

    std::atomic<size_t> m_pendingEventCount{0}; // 等待执行的事件数量
    RWMutexType m_mutex;
    std::vector<FdContext*> m_fdContexts;        // 每个句柄的上下文数组
};

}

#endif